package com.dragon.service.impl;

import cn.hutool.core.io.FileUtil;
import com.alibaba.dashscope.aigc.generation.GenerationParam;
import com.alibaba.dashscope.common.Message;
import com.alibaba.dashscope.common.ResponseFormat;
import com.alibaba.dashscope.common.Role;
import com.alibaba.fastjson.JSON;
import com.dragon.mapper.ProblemMapper;
import com.dragon.mapper.RecordMapper;
import com.dragon.pojo.Problem.JudgeInfo;
import com.dragon.pojo.Problem.Problem;
import com.dragon.pojo.Problem.SubmitInfo;
import com.dragon.pojo.Record.RecordInfo;
import com.dragon.service.DashScopeService;
import com.dragon.service.ProblemService;
import com.dragon.utils.DashScopeUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import reactor.core.publisher.Flux;

import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.CompletableFuture;

@Service
@Slf4j
public class DashScopeServiceImpl implements DashScopeService {
    @Autowired
    RecordMapper recordMapper;
    @Autowired
    ProblemMapper problemMapper;
    @Autowired
    ProblemService problemService;

    @Override
    public Flux<String> smartAnalysis(Integer recordId) {
        // 获取提交记录信息
        RecordInfo recordInfo = recordMapper.getRecordInfo(recordId);
        if(recordInfo == null) {
            return Flux.just("提交记录不存在");
        }
        Integer problemId = recordInfo.getProblemId();
        // 获取题目信息
        Problem problemInfo = problemMapper.getProblemBaseInfo(problemId);
        // 获取第一个没通过的用例
        List<JudgeInfo> pointList = recordInfo.getPointList();
        String input = "";
        String expectOutput = "";
        String judgeResult = "";
        String output;
        String code = FileUtil.readUtf8String(recordInfo.getCodePath());
        for (int i = 0; i < pointList.size(); i++) {
            if (!pointList.get(i).getRunResult().equals("Accepted")) {
                input = problemInfo.getInputList().get(i);
                expectOutput = problemInfo.getOutputList().get(i);
                judgeResult = pointList.get(i).getRunResult();
                break;
            }
        }
        SubmitInfo submitInfo = SubmitInfo.builder()
                .problemId(problemId)
                .language(recordInfo.getLanguage())
                .code(code)
                .input(input)
                .build();
        output  = problemService.testSubmit(submitInfo);
        String promptTemplate = """
        <prompt>
            <instructions>
                <role>你是一位资深的编程竞赛教练。</role>
                <task>
                你的任务是分析用户提供的代码，并针对给定的失败测试用例，找出其中核心的逻辑错误。
                </task>
                <style_guidelines>
                    - 你的分析需要快、准、狠，一针见血地指出问题所在的方向。
                    - 不要直接给出修改后的代码或明确的修复方案。
                    - 使用启发性的问题来引导用户自己思考，比如苏格拉底式提问。
                    - 措辞要像一个耐心且经验丰富的老师，既要指出问题关键，也要给予鼓励。
                    - 最终的回答内容应保持简洁，直击要害。
                    - 输出必须为JSON格式。
                </style_guidelines>
            </instructions>
        
            <examples>
                <example>
                        <user_query>
                            <problem_description>
                            判断一个字符串是否是回文串（忽略大小写和非字母数字字符）。
                            </problem_description>
                            <user_code>
                            <![CDATA[
                            class Solution {
                                public boolean isPalindrome(String s) {
                                    s = s.toLowerCase();
                                    int left = 0;
                                    int right = s.length() - 1;
                                    while (left < right - 1) {\s
                                        if (s.charAt(left) != s.charAt(right)) {
                                            return false;
                                        }
                                        left++;
                                        right--;
                                    }
                                    return true;
                                }
                            }
                            ]]>
                            </user_code>
                            <failed_test_case>
                                <input>"abba"</input>
                                <judgeResult>Wrong Answer</judgeResult>
                                <expected_output>true</expected_output>
                                <actual_output>false</actual_output>
                            </failed_test_case>
                        </user_query>
                       \s
                        <ideal_ai_response>
                            <reasoning_steps>
                            1. **分析代码逻辑**: 用户使用了双指针`left`和`right`，从字符串两端向中间移动，比较对应字符。这是一个正确的算法思路。
                            2. **模拟执行过程**: 使用失败的测试用例`"abba"`来模拟代码执行。
                               - 初始状态: `left = 0`, `right = 3`。`s[0]`是'a', `s[3]`是'a'。
                               - 循环条件检查: `left < right - 1` (即 `0 < 2`)，条件成立。
                               - 第一次循环: `s[0] == s[3]`，字符相等。`left`变为`1`，`right`变为`2`。
                               - 第二次循环条件检查: `left < right - 1` (即 `1 < 1`)，条件**不成立**。循环终止。
                            3. **定位根本原因**: 循环提前终止了。当`left`为1, `right`为2时，本应该再比较一次`s[1]`('b')和`s[2]`('b')，但因为循环条件是`left < right - 1`，导致检查被跳过。
                            4. **构建启发性提示**: 基于以上分析，我需要引导用户去关注循环的终止条件，并让他们思考一个偶数长度的字符串在最后一步比较时，`left`和`right`指针应该处于什么状态。
                            </reasoning_steps>
                           \s
                            <output_json>
                            <![CDATA[
                            {
                              "errorType": "边界条件错误",
                              "hint": "你的双指针算法思路非常清晰！代码离成功只有一步之遥。让我们聚焦于`while`循环的终止条件上。试着在纸上模拟一下当输入是`\\"abba\\"`时，`left`和`right`指针是如何移动的。当它们分别指向中间的两个'b'时，你的循环停下来了吗？还是继续了呢？思考一下循环的边界条件对于奇数和偶数长度的字符串应该有什么不同。",
                              "suggestedEdgeCase": "racecar"
                            }
                            ]]>
                            </output_json>
                        </ideal_ai_response>
                    </example>
            </examples>
        
            <user_query>
                <problem_description>
                    {problem_description}
                </problem_description>
                <user_code>
                    <![CDATA[
                        {code}
                    ]]>
                </user_code>
                <failed_test_case>
                    <judgeResult>{judgeResult}</judgeResult>
                    <input>{input}</input>
                    <expected_output>{expectOutput}</expected_output>
                    <actual_output>{output}</actual_output>
                </failed_test_case>
            </user_query>
        </prompt>
        """;
        // 动态替换占位符
        String finalPrompt = promptTemplate
                .replace("{problem_description}", problemInfo.getDescription()) // 题目描述
                .replace("{code}", code) // 用户代码
                .replace("{judgeResult}", judgeResult) // 输入
                .replace("{input}", input) // 输入
                .replace("{expectOutput}", expectOutput) // 预期输出
                .replace("{output}", output); // 实际输出
//        log.info(finalPrompt);
        // 系统提示词
        Message systemMsg = Message.builder().role("system")
                .content(finalPrompt)
                .build();
        // 将系统提示词和用户消息放到一个list中
        List<Message> messages = Collections.singletonList(systemMsg);
        GenerationParam param = GenerationParam.builder()
                .model("qwen3-coder-plus") // 模型名称
                .incrementalOutput(true)
                .resultFormat("message")
                .temperature(0.7F)
                .responseFormat(ResponseFormat.builder().type("json_object").build())
                .messages(messages)
                .build();
        return DashScopeUtils.runFlux(param);
    }

    @Override
    public CompletableFuture<Problem> smartSetQuestion(String text) {
        String systemText =
                "你是一个资深的编程竞赛出题专家。现在给你一个JSON模式，用生成的信息填充该模式的值的部分，如果没有对应的值则用null填充。" +
                "请分析用户传递的算法思想，创建一个编程题目，生成题目信息。" +
                "你的任务是：" +
                "1. 生成标题、描述、算法标签、说明提示、时间限制(ms)、内存限制(KB)，且算法标签个数不超过三个。" +
                "2. 生成清晰的输入输出格式描述。" +
                "3. 生成若干组测试用例，包括基础、边界和压力测试用例。" +
                "4. 输入样例与输出样例、输入列表与输出列表的个数必须相同。" +
                "5. 输入输出样例个数不超过5个、输入输出列表个数不超过15个。设置数量需合理" +
                "请严格按要求输出结果。输入的JSON Schema如下: \n" +
                """
                "type": "object",
                "properties": {
                    "titleName": {
                        "type": "string",
                        "title": "标题"
                    },
                    "inputExample": {
                        "type": "array",
                        "items": {
                            "type": "string"
                        },
                        "title": "样例输入"
                    },
                    "outputExample": {
                        "type": "array",
                        "items": {
                            "type": "string"
                        },
                        "title": "样例输出"
                    },
                    "description": {
                        "type": "string",
                        "title": "描述"
                    },
                    "timeLimit": {
                        "type": "integer",
                        "title": "限制时间",
                        "description": "单位：ms"
                    },
                    "memoryLimit": {
                        "type": "integer",
                        "title": "内存限制"
                    },
                    "difficulty": {
                        "type": "integer",
                        "title": "题目难度",
                        "description": "0-所有 1-暂无评定 2-简单 3-普通 4-困难"
                    },
                    "algorithmTag": {
                        "type": "array",
                        "items": {
                            "type": "string"
                        },
                        "title": "算法标签"
                    },
                    "inputFormat": {
                        "type": "string",
                        "title": "输入格式"
                    },
                    "outputFormat": {
                        "type": "string",
                        "title": "输出格式"
                    },
                    "tips": {
                        "type": "string",
                        "title": "说明/提示"
                    },
                    "inputList": {
                        "type": "array",
                        "items": {
                            "type": "string"
                        },
                        "title": "测试点输入"
                    },
                    "outputList": {
                        "type": "array",
                        "items": {
                            "type": "string"
                        },
                        "title": "测试点输入"
                    }
                }
                """;
        // 将系统提示词和用户消息放到一个list中
        // 系统提示词
        Message systemMsg = Message.builder().role("system")
                .content(systemText)
                .build();
        // 用户消息
        Message userMsg = Message.builder()
                .role(Role.USER.getValue())
                .content(text)
                .build();
        List<Message> messages = Arrays.asList(systemMsg, userMsg);
        GenerationParam param = GenerationParam.builder()
                .model("qwen3-coder-plus") // 模型名称
                .incrementalOutput(true)
                .resultFormat("message")
                .messages(messages)
                .temperature(1.5F)
                .responseFormat(ResponseFormat.builder().type("json_object").build())
                .build();
        CompletableFuture<String> resultFuture  = DashScopeUtils.runNoFlux(param);
        return resultFuture.thenApply(jsonString -> {
            log.info("--- 获取到JSON字符串，开始解析 ---");
            log.info(jsonString);
            // 进行解析和转换
            return JSON.parseObject(jsonString, Problem.class);
        }).exceptionally(e -> {
            log.error("处理AI结果或解析JSON时出错: {}", e.getMessage(), e);
            return new Problem();
        });
    }
}